//
//  ScenesAudioCodec.cpp
//  ScenesPlayer
//
//  Created by Branch on 2016/11/2.
//  Copyright © 2016年 Scenes. All rights reserved.
//

#include "ScenesAudioCodec.h"
#include <pthread.h>
#include "IAudioDecoderFactory.h"
#include "IAudioDecoder.h"
#include <stdlib.h>
#include <unistd.h>
#include "utils/log.h"


static void* syn_openMovie(void* pPrama){
    ((ScenesAudioCodec*)pPrama)->runThread();
    return NULL;
}

ScenesAudioCodec::ScenesAudioCodec()
: _audioDecoder(NULL)
, _audioDecoderFactory(NULL)
, _scenesAudioCodecCallback(NULL)
, _userData(NULL)
, _streamIndex(0)
, _isEndThread(NULL)
, _isClean(false)

{
    
}


ScenesAudioCodec::~ScenesAudioCodec(){
    
}




bool ScenesAudioCodec::openDecoder(IAudioDecoderFactory* audioDecoderFactory,
                 int streamIndex,
                 ScenesAudioCodecCallback callback,
                 void* userData){
    _audioDecoderFactory = audioDecoderFactory;
    _streamIndex = streamIndex;
    _scenesAudioCodecCallback = callback;
    _userData = userData;
    
    _audioDecoder = audioDecoderFactory->createAudioDecoder();
    //AndroidAudioDecoder* decoder = new AndroidAudioDecoder();
    //decoder->openAudioDecoder();
    //_audioDecoder = decoder;
    pthread_t pt;
    
    pthread_create(&pt, NULL, &syn_openMovie, this);
    return true;
    
}

void ScenesAudioCodec::shutdown(){
    if (_isEndThread) {
        *_isEndThread = true;
        _lock.lock();
        //*_isEndThread = true;
        _lock.unlock();
    }

    
    _audioDecoderFactory->destroyAudioDecoder(_audioDecoder);
    _audioDecoder = NULL;
    _audioDecoderFactory = NULL;
    doClean();
}

void ScenesAudioCodec::clean(){
    _isClean = true;

}

void ScenesAudioCodec::doClean(){

    _queue_lock.lock();
    while (_audioQueue.size() > 0) {
        StAudioBuff info = _audioQueue.front();
        _audioQueue.pop();
        free(info.buff) ;
    }
    _queue_lock.unlock();
//    if(_audioDecoder){
//       _audioDecoder->flush(); 
//    }
    
}

bool ScenesAudioCodec::inputBuff(uint8_t* buff,uint32_t len,int64_t presentationTimeUs){
    bool ret = false;
    StAudioBuff info;
    
    info.buff = (uint8_t*)malloc(len);;
    memcpy(info.buff, buff, len);
    info.len = len;
    info.presentationTimeUs = presentationTimeUs;
    //clock_t start =  clock();

    _queue_lock.lock();
    _audioQueue.push(info);
    _queue_lock.unlock();
    


    return ret;
}

uint32_t ScenesAudioCodec::getCacheSize(){
    uint32_t ret = 0;
    ret = (uint32_t)_audioQueue.size();

    return ret;
}

void ScenesAudioCodec::doDecode(){
    StAudioBuff info;
    info.buff = NULL;
    _queue_lock.lock();
    if (!_audioQueue.empty()) {
        info = _audioQueue.front();
    }
    _queue_lock.unlock();
    if(info.buff != NULL){

        if(_audioDecoder->inputBuff(info.buff, info.len, info.presentationTimeUs)){
            
            _queue_lock.lock();
            _audioQueue.pop();
            free(info.buff);
            _queue_lock.unlock();
            
            
        }else{
            
        }
    }else{
        usleep(10000);
    }

    uint8_t* out_buff = NULL;
    uint32_t out_buffLen = 0;
    int64_t out_sampleTimeUs = 0;
    if (_audioDecoder->outputBuff(&out_buff, &out_buffLen, &out_sampleTimeUs)){

        
        if (_scenesAudioCodecCallback != NULL) {
            
            _scenesAudioCodecCallback(out_buff,out_buffLen,out_sampleTimeUs,
                                      _streamIndex,_userData);
        }

    }else{

    }
    
    
    

}

void ScenesAudioCodec::runThread(){
    bool isEndThread = false;
    _isEndThread = &isEndThread;
    _isClean = false;
    while (true) {

        _lock.lock();
        if (isEndThread) {
            _lock.unlock();
            break;
        }
        if (_isClean) {
            _isClean = false;
            doClean();
        }
        doDecode();
        _lock.unlock();
        
    }
    
    
    
}
